#ifndef TESTCASESHELPER_H
#define TESTCASESHELPER_H

#include "TestCasesBase.h"

template< typename T, int maxTests > class TestCasesHelper;

namespace Detail {
  struct RunHelperBase {
    template< typename T, int maxTests, int testNo >
    inline int CallRunner( TestCasesHelper< T, maxTests >& hlpr, int prevTest ) {
      return hlpr. template Runner< testNo >( prevTest );
    }
  };
  template< typename T, int maxTests, int testNo >
  struct RunHelper: public RunHelperBase {
    public:
      inline int Run( TestCasesHelper< T, maxTests >& hlpr ) {
        return CallRunner< T, maxTests, testNo >( hlpr, RunHelper < T, maxTests, testNo - 1 > ().Run( hlpr ) );
      }
  };
  template< typename T, int maxTests >
struct RunHelper<T, maxTests, 0 > { public: inline int Run( TestCasesHelper< T, maxTests >& ) { return 0; } };
}

template< typename T, int maxTests = 50 >
class TestCasesHelper: public T, public TestCasesBase {
  public:
    virtual bool PerformTests() {
      return RunTests();
    }
    template< int i >
    void Test() {
      m_NoSuchTest = true;
    }
    void Ensure( bool condition, const wxString& failMsg ) {
      if( !condition ) {
        TestError err;
        err.m_Msg = failMsg;
        throw err;
      }
    }

  private:
    inline bool RunTests() {
      m_FailCnt = 0;
      m_PassCnt = 0;
      m_SkipCnt = 0;
      Detail::RunHelper< T, maxTests, maxTests > ().Run( *this );
      AddLog( wxString::Format( _T( "===============================" ) ) );
      AddLog( wxString::Format( _T( "概要:" ) ) );
      AddLog( wxString::Format( _T( " 通过: %d" ), m_PassCnt ) );
      AddLog( wxString::Format( _T( " 失败: %d" ), m_FailCnt ) );
      AddLog( wxString::Format( _T( "  总计: %d" ), m_PassCnt + m_FailCnt ) );
      return m_FailCnt == 0;
    }
    template< int testNo >
    inline int Runner( int prevTest ) {
      if( StopTest() ) {
        return testNo;
      }
      wxString result;
      bool pass = true;
      m_NoSuchTest = false;
      try {
        Test< testNo >();
      } catch( const TestError& err ) {
        pass = false;
        result = wxString::Format( _T( "Test %d 失败: %s" ), testNo, err.m_Msg.wx_str() );
      }
      if( m_NoSuchTest ) {
        m_SkipCnt++;
        return prevTest;
      }
      for( int i = prevTest + 1; i < testNo; i++ ) {
        AddLog( wxString::Format( _T( "Test %d 跳过: 未定义" ), i ) );
      }
      AddLog( pass ? wxString::Format( _T( "Test %d 通过" ), testNo ) : result );
      ( pass ? m_PassCnt : m_FailCnt ) ++;
      return testNo;
    }
    struct TestError { wxString m_Msg; };
    int m_FailCnt;
    int m_PassCnt;
    int m_SkipCnt;
    bool m_NoSuchTest;
    friend class Detail::RunHelperBase;
};

#endif
